using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Net35.Xrm.Sdk.Linq
{
	internal static class ExpressionExtensions
	{
		public delegate void ExpressionAction(Expression exp, Expression parent);
		public static void ForSubtreePreorder(this Expression exp, ExpressionExtensions.ExpressionAction action)
		{
			exp.ForSubtreePreorder(null, action);
		}
		public static void ForSubtreePreorder(this Expression exp, Expression parent, ExpressionExtensions.ExpressionAction action)
		{
			action(exp, parent);
			foreach (Expression current in exp.GetChildren())
			{
				current.ForSubtreePreorder(exp, action);
			}
		}
		public static IEnumerable<Expression> GetChildren(this Expression exp)
		{
			if (exp is UnaryExpression)
			{
				yield return ((UnaryExpression)exp).Operand;
			}
			else if (exp is BinaryExpression)
			{
				yield return ((BinaryExpression)exp).Left;
				yield return ((BinaryExpression)exp).Right;
				yield return ((BinaryExpression)exp).Conversion;
			}
			else if (exp is TypeBinaryExpression)
			{
				yield return ((TypeBinaryExpression)exp).Expression;
			}
			else if (exp is ConditionalExpression)
			{
				yield return ((ConditionalExpression)exp).Test;
				yield return ((ConditionalExpression)exp).IfTrue;
				yield return ((ConditionalExpression)exp).IfFalse;
			}
			else if (exp is MemberExpression)
			{
				yield return ((MemberExpression)exp).Expression;
			}
			else if (exp is MethodCallExpression)
			{
				yield return ((MethodCallExpression)exp).Object;
				foreach (Expression current in ((MethodCallExpression)exp).Arguments)
				{
					yield return current;
				}
			}
			else if (exp is LambdaExpression)
			{
				yield return ((LambdaExpression)exp).Body;
				foreach (ParameterExpression current2 in ((LambdaExpression)exp).Parameters)
				{
					yield return current2;
				}
			}
			else if (exp is NewExpression)
			{
				foreach (Expression current3 in ((NewExpression)exp).Arguments)
				{
					yield return current3;
				}
			}
			else if (exp is NewArrayExpression)
			{
				foreach (Expression current4 in ((NewArrayExpression)exp).Expressions)
				{
					yield return current4;
				}
			}
			else if (exp is InvocationExpression)
			{
				yield return ((InvocationExpression)exp).Expression;
				foreach (Expression current5 in ((InvocationExpression)exp).Arguments)
				{
					yield return current5;
				}
			}
			else if (exp is MemberInitExpression)
			{
				yield return ((MemberInitExpression)exp).NewExpression;
				foreach (Expression current6 in ExpressionExtensions.GetChildren(((MemberInitExpression)exp).Bindings))
				{
					yield return current6;
				}
			}
			else if (exp is ListInitExpression)
			{
				yield return ((ListInitExpression)exp).NewExpression;
				foreach (Expression current7 in ExpressionExtensions.GetChildren(((ListInitExpression)exp).Initializers))
				{
					yield return current7;
				}
			}
			yield break;
		}
		private static IEnumerable<Expression> GetChildren(IEnumerable<MemberBinding> bindings)
		{
			return bindings.SelectMany(new Func<MemberBinding, IEnumerable<Expression>>(ExpressionExtensions.GetChildren));
		}
		private static IEnumerable<Expression> GetChildren(MemberBinding binding)
		{
			switch (binding.BindingType)
			{
			case MemberBindingType.Assignment:
				yield return ((MemberAssignment)binding).Expression;
				break;
			case MemberBindingType.MemberBinding:
				foreach (Expression current in ExpressionExtensions.GetChildren(((MemberMemberBinding)binding).Bindings))
				{
					yield return current;
				}
				break;
			case MemberBindingType.ListBinding:
				foreach (Expression current2 in ExpressionExtensions.GetChildren(((MemberListBinding)binding).Initializers))
				{
					yield return current2;
				}
				break;
			}
			yield break;
		}
		private static IEnumerable<Expression> GetChildren(IEnumerable<ElementInit> initializers)
		{
			return initializers.SelectMany((ElementInit initializer) => initializer.Arguments);
		}
		public static IEnumerable<Expression> GetSubtreePreorder(this Expression exp)
		{
			yield return exp;
			foreach (Expression current in exp.GetChildren().SelectMany((Expression child) => child.GetSubtreePreorder()))
			{
				yield return current;
			}
			yield break;
		}
		public static Expression FindPreorder(this Expression exp, Predicate<Expression> match)
		{
			return exp.GetSubtreePreorder().FirstOrDefault((Expression child) => match(child));
		}
		public static IEnumerable<MethodCallExpression> GetMethodsPreorder(this Expression exp)
		{
			MethodCallExpression methodCallExpression = exp as MethodCallExpression;
			if (methodCallExpression != null)
			{
				yield return methodCallExpression;
				foreach (MethodCallExpression current in methodCallExpression.Arguments[0].GetMethodsPreorder())
				{
					yield return current;
				}
			}
			yield break;
		}
		public static IEnumerable<MethodCallExpression> GetMethodsPostorder(this Expression exp)
		{
			MethodCallExpression methodCallExpression = exp as MethodCallExpression;
			if (methodCallExpression != null)
			{
				foreach (MethodCallExpression current in methodCallExpression.Arguments[0].GetMethodsPostorder())
				{
					yield return current;
				}
				yield return methodCallExpression;
			}
			yield break;
		}
	}
}
